/**
 * Copyright (c) 2018 软唐 All rights reserved.
 * <p>
 * https://www.softtown.cn
 * <p>
 * 版权所有，侵权必究！
 */

package com.softtown.modules.security.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qcloud.cos.utils.StringUtils;
import com.softtown.common.annotation.LogOperation;
import com.softtown.common.constant.Constant;
import com.softtown.common.constant.Constant.MiniService;
import com.softtown.common.enums.MsgSendWayTypeEnum;
import com.softtown.common.enums.MsgTypeEnum;
import com.softtown.common.enums.SystemModelEnum;
import com.softtown.common.exception.ErrorCode;
import com.softtown.common.exception.RenException;
import com.softtown.common.regularUtils.RegularUtils;
import com.softtown.common.utils.ConvertUtils;
import com.softtown.common.utils.IpUtils;
import com.softtown.common.utils.Result;
import com.softtown.common.validator.AssertUtils;
import com.softtown.common.validator.ValidatorUtils;
import com.softtown.common.validator.group.UpdateGroup;
import com.softtown.license.license.CustomLicenseManager;
import com.softtown.modules.log.entity.SysLogLoginEntity;
import com.softtown.modules.log.enums.LoginOperationEnum;
import com.softtown.modules.log.enums.LoginStatusEnum;
import com.softtown.modules.log.service.SysLogLoginService;
import com.softtown.modules.message.entity.SysEmailContentEntity;
import com.softtown.modules.message.service.SysEmailContentService;
import com.softtown.modules.message.sms.AbstractSmsService;
import com.softtown.modules.message.sms.SmsFactory;
import com.softtown.modules.oss.cloud.CloudStorageConfig;
import com.softtown.modules.security.config.AES;
import com.softtown.modules.security.dto.LoginBySmsCodeDTO;
import com.softtown.modules.security.dto.LoginDTO;
import com.softtown.modules.security.dto.LoginOpenIdDTO;
import com.softtown.modules.security.dto.LoginOutDTO;
import com.softtown.modules.security.dto.ResetDTO;
import com.softtown.modules.security.dto.WxOpenIdDTO;
import com.softtown.modules.security.entity.SysSmsContentEntity;
import com.softtown.modules.security.password.PasswordUtils;
import com.softtown.modules.security.service.CaptchaService;
import com.softtown.modules.security.service.SysSmsContentService;
import com.softtown.modules.security.service.SysUserTokenService;
import com.softtown.modules.security.user.SecurityUser;
import com.softtown.modules.security.user.UserDetail;
import com.softtown.modules.sys.MiniProgramConfig;
import com.softtown.modules.sys.dto.AppealDTO;
import com.softtown.modules.sys.dto.SysUserDTO;
import com.softtown.modules.sys.entity.SysFeedBackEntity;
import com.softtown.modules.sys.entity.SysMsgSendWayEntity;
import com.softtown.modules.sys.entity.SysUserEntity;
import com.softtown.modules.sys.enums.FeedBackTypeEnum;
import com.softtown.modules.sys.enums.FeedbackStatusEnum;
import com.softtown.modules.sys.enums.InitUserStatusEnum;
import com.softtown.modules.sys.enums.UserStatusEnum;
import com.softtown.modules.sys.service.SysMsgSendWayService;
import com.softtown.modules.sys.service.SysParamsService;
import com.softtown.modules.sys.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidAlgorithmParameterException;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录
 *
 * @author Ding Ya Yong
 */
@RestController
@Api(tags = "登录管理")
public class LoginController {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserTokenService sysUserTokenService;

    @Resource
    private CaptchaService captchaService;

    @Resource
    private SysLogLoginService sysLogLoginService;

    @Resource
    private SysSmsContentService sysSmsContentService;

    @Resource
    private SysMsgSendWayService sysMsgSendWayService;

    @Resource
    private SysEmailContentService sysEmailContentService;

    @Resource
    private SysParamsService sysParamsService;

    private static final int LENGTH = 11;


    public static Map<String, Object> openidMap = new HashMap<String, Object>();

    @GetMapping("captcha")
    @ApiOperation(value = "验证码", produces = "application/octet-stream")
    @ApiImplicitParam(paramType = "query", dataType = "string", name = "uuid", required = true)
    public void captcha(HttpServletResponse response, String uuid) throws IOException {
        //uuid不能为空
        AssertUtils.isBlank(uuid, ErrorCode.IDENTIFIER_NOT_NULL);

        //生成图片验证码
        BufferedImage image = captchaService.create(uuid);

        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        out.close();
    }

    /**
     * 快速登录
     *
     * @param
     * @return
     * @author Dingyayong
     * @date 2019/12/5 13:32
     */
    @PostMapping("sendSms")
    @ApiOperation(value = "发送短息")
    @LogOperation("发送短息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "query", required = true, dataType = "String"),
    })
    public Result sendSms(@RequestBody String mobile) {
        Map<String, Object> paramMap = JSONObject.fromObject(mobile);
        String phone = paramMap.get("mobile").toString();
        // TODO
        String type = "短信验证码登录";
        Result result = new Result<>();
        if (StringUtils.isNullOrEmpty(phone)) {
            return result.error(ErrorCode.MOBILE_EMPTY);
        }
        if (!RegularUtils.isMobile(phone)) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        if (phone.length() != LENGTH) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        Map<String, Object> map = new HashMap<>(16);
        // 32261-32281
        SysMsgSendWayEntity sysMsgSendWayEntity = sysMsgSendWayService
            .selectBySendTypeAndType(MsgSendWayTypeEnum.
                SMS.value(), MsgTypeEnum.PHONE_FAST_CODE.value());
        String smsCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        try {
            //短信服务
            AbstractSmsService service = SmsFactory.build();
            if (service == null) {
                throw new RenException(ErrorCode.SMS_CONFIG);
            }
            String jsonString = service
                .sendSmsByLogin(phone, sysMsgSendWayEntity.getMsgTemplateCode(),
                    smsCode + "|" + type);
            map = JSONObject.fromObject(jsonString);
            if (!map.isEmpty() && map.get("Code").toString().equals("OK")) {
                // 短信验证码表
                SysSmsContentEntity sysSmsContentEntity = sysSmsContentService.getByMobile(phone);
                // 短信验证码默认有效时间--十分钟
                String smsValidateTime = Constant.SMS_CODEVALIDATE;
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MINUTE, Integer.parseInt(smsValidateTime));
                // 数据库不存在该短信验证码
                if (sysSmsContentEntity == null) {
                    // 短信验证码表 保存数据
                    SysSmsContentEntity sysSmsContentEntitys = new SysSmsContentEntity();
                    sysSmsContentEntitys.setMobile(phone);
                    sysSmsContentEntitys.setSmsCode(smsCode);
                    sysSmsContentEntitys.setSmsExpiresAt(calendar.getTime());
                    // 用于页面验证码输入后提交
                    sysSmsContentService.saveSms(sysSmsContentEntitys);
                } else {
                    // 存在的场合更新对应的验证码
                    sysSmsContentEntity.setSmsCode(smsCode);
                    sysSmsContentEntity.setSmsExpiresAt(calendar.getTime());
                    sysSmsContentService.updateSmsCode(sysSmsContentEntity);
                }
                //按钮重置倒计时（秒）
                map.put("smsValidateTime", Integer.parseInt(smsValidateTime) * 60);
                map.put("code", "0");
                map.put("sms_code", smsCode);
                map.remove("message_id");
                map.remove("request_id");
            } else {
                map.put("code", "1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 注册发送短息
     *
     * @param
     * @return
     * @author Dingyayong
     * @date 2019/12/5 13:32
     */
    @PostMapping("sendSmsByRegister")
    @ApiOperation(value = "注册发送短息")
    @LogOperation("注册发送短息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "query", required = true, dataType = "String"),
    })
    public Result sendSmsByRegister(@RequestBody String mobile) {
        Map<String, Object> paramMap = JSONObject.fromObject(mobile);
        String phone = paramMap.get("mobile").toString();
        String type = "新用户注册";
        Result result = new Result<>();
        if (StringUtils.isNullOrEmpty(phone)) {
            return result.error(ErrorCode.MOBILE_EMPTY);
        }
        if (!RegularUtils.isMobile(phone)) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        if (phone.length() != LENGTH) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        Map<String, Object> map = new HashMap<>(16);
        // 32261-32281
        SysMsgSendWayEntity sysMsgSendWayEntity = sysMsgSendWayService
            .selectBySendTypeAndType(MsgSendWayTypeEnum.
                SMS.value(), MsgTypeEnum.PHONE_REGISTER_CODE.value());
        String smsCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        try {
            //短信服务
            AbstractSmsService service = SmsFactory.build();
            if (service == null) {
                throw new RenException(ErrorCode.SMS_CONFIG);
            }
            String jsonString = service
                .sendSmsByLogin(phone, sysMsgSendWayEntity.getMsgTemplateCode(),
                    smsCode + "|" + type);
            map = JSONObject.fromObject(jsonString);
            if (!map.isEmpty() && map.get("Code").toString().equals("OK")) {
                // 短信验证码表
                SysSmsContentEntity sysSmsContentEntity = sysSmsContentService.getByMobile(phone);
                // 短信验证码默认有效时间--十分钟
                String smsValidateTime = Constant.SMS_CODEVALIDATE;
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MINUTE, Integer.parseInt(smsValidateTime));
                // 数据库不存在该短信验证码
                if (sysSmsContentEntity == null) {
                    // 短信验证码表 保存数据
                    SysSmsContentEntity sysSmsContentEntitys = new SysSmsContentEntity();
                    sysSmsContentEntitys.setMobile(phone);
                    sysSmsContentEntitys.setSmsCode(smsCode);
                    sysSmsContentEntitys.setSmsExpiresAt(calendar.getTime());
                    // 用于页面验证码输入后提交
                    sysSmsContentService.saveSms(sysSmsContentEntitys);
                } else {
                    // 存在的场合更新对应的验证码
                    sysSmsContentEntity.setSmsCode(smsCode);
                    sysSmsContentEntity.setSmsExpiresAt(calendar.getTime());
                    sysSmsContentService.updateSmsCode(sysSmsContentEntity);
                }
                //按钮重置倒计时（秒）
                map.put("smsValidateTime", Integer.parseInt(smsValidateTime) * 60);
                map.put("code", "0");
                map.put("sms_code", smsCode);
                map.remove("message_id");
                map.remove("request_id");
            } else {
                map.put("code", "1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 忘记密码重置发送短息
     *
     * @param
     * @return
     * @author Dingyayong
     * @date 2019/12/5 13:32
     */
    @PostMapping("sendSmsByRestPassword")
    @ApiOperation(value = "忘记密码重置发送短息")
    @LogOperation("忘记密码重置发送短息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "query", required = true, dataType = "String"),
    })
    public Result sendSmsByRestPassword(@RequestBody String mobile) {
        Map<String, Object> paramMap = JSONObject.fromObject(mobile);
        String phone = paramMap.get("mobile").toString();
        String type = "重置密码";
        Result result = new Result<>();
        if (StringUtils.isNullOrEmpty(phone)) {
            return result.error(ErrorCode.MOBILE_EMPTY);
        }
        if (!RegularUtils.isMobile(phone)) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        if (phone.length() != LENGTH) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        Map<String, Object> map = new HashMap<>(16);
        // 32261-32281
        SysMsgSendWayEntity sysMsgSendWayEntity = sysMsgSendWayService
            .selectBySendTypeAndType(MsgSendWayTypeEnum.
                SMS.value(), MsgTypeEnum.PHONE_RESET_CODE.value());
        String smsCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        try {
            //短信服务
            AbstractSmsService service = SmsFactory.build();
            if (service == null) {
                throw new RenException(ErrorCode.SMS_CONFIG);
            }
            String jsonString = service
                .sendSmsByLogin(phone, sysMsgSendWayEntity.getMsgTemplateCode(),
                    smsCode + "|" + type);
            map = JSONObject.fromObject(jsonString);
            if (!map.isEmpty() && map.get("Code").toString().equals("OK")) {
                // 短信验证码表
                SysSmsContentEntity sysSmsContentEntity = sysSmsContentService.getByMobile(phone);
                // 短信验证码默认有效时间--十分钟
                String smsValidateTime = Constant.SMS_CODEVALIDATE;
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MINUTE, Integer.parseInt(smsValidateTime));
                // 数据库不存在该短信验证码
                if (sysSmsContentEntity == null) {
                    // 短信验证码表 保存数据
                    SysSmsContentEntity sysSmsContentEntitys = new SysSmsContentEntity();
                    sysSmsContentEntitys.setMobile(phone);
                    sysSmsContentEntitys.setSmsCode(smsCode);
                    sysSmsContentEntitys.setSmsExpiresAt(calendar.getTime());
                    // 用于页面验证码输入后提交
                    sysSmsContentService.saveSms(sysSmsContentEntitys);
                } else {
                    // 存在的场合更新对应的验证码
                    sysSmsContentEntity.setSmsCode(smsCode);
                    sysSmsContentEntity.setSmsExpiresAt(calendar.getTime());
                    sysSmsContentService.updateSmsCode(sysSmsContentEntity);
                }
                //按钮重置倒计时（秒）
                map.put("smsValidateTime", Integer.parseInt(smsValidateTime) * 60);
                map.put("code", "0");
                map.put("sms_code", smsCode);
                map.remove("message_id");
                map.remove("request_id");
            } else {
                map.put("code", "1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * 手机号更换时向新手机号验证码发送
     *
     * @param
     * @return
     * @author Dingyayong
     * @date 2019/12/5 13:32
     */
    @PostMapping("sendSmsByChangePhone")
    @ApiOperation(value = "手机号更换时向新手机号验证码发送")
    @LogOperation("手机号更换时向新手机号验证码发送")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "query", required = true, dataType = "String"),
    })
    public Result sendSmsByChangePhone(@RequestBody String mobile) {
        Map<String, Object> paramMap = JSONObject.fromObject(mobile);
        String phone = paramMap.get("mobile").toString();
        String type = "绑定新手机号";
        Result result = new Result<>();
        if (StringUtils.isNullOrEmpty(phone)) {
            return result.error(ErrorCode.MOBILE_EMPTY);
        }
        if (!RegularUtils.isMobile(phone)) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        if (phone.length() != LENGTH) {
            return result.error(ErrorCode.MOBILE_ERROR);
        }
        Map<String, Object> map = new HashMap<>(16);
        // 32261-32281
        SysMsgSendWayEntity sysMsgSendWayEntity = sysMsgSendWayService
            .selectBySendTypeAndType(MsgSendWayTypeEnum.
                SMS.value(), MsgTypeEnum.PHONE_CHANGE_CODE.value());
        String smsCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        try {
            //短信服务
            AbstractSmsService service = SmsFactory.build();
            if (service == null) {
                throw new RenException(ErrorCode.SMS_CONFIG);
            }
            String jsonString = service
                .sendSmsByLogin(phone, sysMsgSendWayEntity.getMsgTemplateCode(),
                    smsCode + "|" + type);
            map = JSONObject.fromObject(jsonString);
            if (!map.isEmpty() && map.get("Code").toString().equals("OK")) {
                // 短信验证码表
                SysSmsContentEntity sysSmsContentEntity = sysSmsContentService.getByMobile(phone);
                // 短信验证码默认有效时间--十分钟
                String smsValidateTime = Constant.SMS_CODEVALIDATE;
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MINUTE, Integer.parseInt(smsValidateTime));
                // 数据库不存在该短信验证码
                if (sysSmsContentEntity == null) {
                    // 短信验证码表 保存数据
                    SysSmsContentEntity sysSmsContentEntitys = new SysSmsContentEntity();
                    sysSmsContentEntitys.setMobile(phone);
                    sysSmsContentEntitys.setSmsCode(smsCode);
                    sysSmsContentEntitys.setSmsExpiresAt(calendar.getTime());
                    // 用于页面验证码输入后提交
                    sysSmsContentService.saveSms(sysSmsContentEntitys);
                } else {
                    // 存在的场合更新对应的验证码
                    sysSmsContentEntity.setSmsCode(smsCode);
                    sysSmsContentEntity.setSmsExpiresAt(calendar.getTime());
                    sysSmsContentService.updateSmsCode(sysSmsContentEntity);
                }
                //按钮重置倒计时（秒）
                map.put("smsValidateTime", Integer.parseInt(smsValidateTime) * 60);
                map.put("code", "0");
                map.put("sms_code", smsCode);
                map.remove("message_id");
                map.remove("request_id");
            } else {
                map.put("code", "1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * @param @param [request, login]
     * @return @return com.softtown.common.utils.Result
     * @throws
     * @Title: login
     * @Description: Saas模式下的账户登录
     * @author fuming
     * @date 2019/5/31 13:04
     */
    @PostMapping("login")
    @ApiOperation(value = "登录")
    @LogOperation("登录")
    public Result login(HttpServletRequest request, @RequestBody LoginDTO login) {
        Integer one = 1;
        //效验数据
        ValidatorUtils.validateEntity(login);
        Result result = new Result<>();
        // 判断如果系统模式为op时
        if (Constant.SYSTEM_MODEL.equals(SystemModelEnum.MODEL_OP.value())) {
            Map<String, Object> codeMap = CustomLicenseManager.codeMap;
            int allUserCount = sysUserTokenService.getAllCompUserCount();
            if (allUserCount > Integer.parseInt(codeMap.get("consumerAmount").toString())) {
                return result.error(ErrorCode.LOGIN_USER_COUNT_ERROR);
            }
        }
        if (RegularUtils.isMobile(login.getUsername())) {
            String mobile = login.getUsername();

            //用户信息
            SysUserDTO user = sysUserService.getByMobile(mobile);
            SysLogLoginEntity log = new SysLogLoginEntity();

            //用户不存在
            if (user == null) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(login.getUsername());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);
            }
            if (user.getIsInitPassword().equals(one)) {
                return result.error(ErrorCode.INIT_MANAGER_PASSWORD);
            }

            //密码错误
            if (!PasswordUtils.matches(login.getPassword(), user.getPassword())) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(user.getUsername());
                log.setCreator(user.getId());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);

            }

            //账号停用
            if (user.getStatus() == UserStatusEnum.DISABLE.value()) {
                log.setStatus(LoginStatusEnum.LOCK.value());
                log.setCreatorName(user.getUsername());
                log.setCreator(user.getId());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_DISABLE);
            }
            log.setOperation(LoginOperationEnum.LOGIN.value());
            log.setIp(IpUtils.getIpAddr(request));
            log.setCreateDate(new Date());
            log.setIp(IpUtils.getIpAddr(request));
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
            //登录成功
            log.setStatus(LoginStatusEnum.SUCCESS.value());
            log.setCreator(user.getId());
            log.setCreatorName(user.getUsername());
            sysLogLoginService.save(log);

            return sysUserTokenService.createToken(user.getId());
        } else if (RegularUtils.isEmail(login.getUsername())) {
            String email = login.getUsername();

            SysLogLoginEntity log = new SysLogLoginEntity();
            //用户信息
            SysUserDTO user = ConvertUtils
                .sourceToTarget(sysUserService.getEntityByEmail(email), SysUserDTO.class);
            //用户不存在
            if (user == null) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(login.getUsername());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);
            }
            if (user.getIsInitPassword().equals(one)) {
                return result.error(ErrorCode.INIT_MANAGER_PASSWORD);
            }

            log.setOperation(LoginOperationEnum.LOGIN.value());
            log.setIp(IpUtils.getIpAddr(request));
            log.setCreateDate(new Date());
            log.setIp(IpUtils.getIpAddr(request));
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));

            //密码错误
            if (!PasswordUtils.matches(login.getPassword(), user.getPassword())) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(user.getUsername());
                log.setCreator(user.getId());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);

            }

            //账号停用
            if (user.getStatus() == UserStatusEnum.DISABLE.value()) {
                log.setStatus(LoginStatusEnum.LOCK.value());
                log.setCreatorName(user.getUsername());
                log.setCreator(user.getId());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_DISABLE);
            }
            //登录成功
            log.setStatus(LoginStatusEnum.SUCCESS.value());
            log.setCreator(user.getId());
            log.setCreatorName(user.getUsername());
            sysLogLoginService.save(log);

            return sysUserTokenService.createToken(user.getId());
        } else {
            //效验数据
            ValidatorUtils.validateEntity(login);

            SysLogLoginEntity log = new SysLogLoginEntity();
            //用户信息
            SysUserDTO user = sysUserService.getByUsername(login.getUsername());
            //用户不存在
            if (user == null) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(login.getUsername());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);
            }
            if (user.getIsInitPassword().equals(one)) {
                return result.error(ErrorCode.INIT_MANAGER_PASSWORD);
            }
            log.setOperation(LoginOperationEnum.LOGIN.value());
            log.setCreateDate(new Date());
            log.setIp(IpUtils.getIpAddr(request));
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
            log.setIp(IpUtils.getIpAddr(request));

            //密码错误
            if (!PasswordUtils.matches(login.getPassword(), user.getPassword())) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreator(user.getId());
                log.setCreatorName(user.getUsername());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_PASSWORD_ERROR);
            }

            //账号停用
            if (user.getStatus() == UserStatusEnum.DISABLE.value()) {
                log.setStatus(LoginStatusEnum.LOCK.value());
                log.setCreator(user.getId());
                log.setCreatorName(user.getUsername());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.ACCOUNT_DISABLE);
            }

            //登录成功
            log.setStatus(LoginStatusEnum.SUCCESS.value());
            log.setCreator(user.getId());
            log.setCreatorName(user.getUsername());
            sysLogLoginService.save(log);

            return sysUserTokenService.createToken(user.getId());
        }

    }

    /**
     * @param @param [request, login]
     * @return @return com.softtown.common.utils.Result
     * @throws
     * @Title: loginBySmsCode
     * @Description: Saas模式下的手机动态码登录
     * @author fuming
     * @date 2019/5/31 13:03
     */
    @PostMapping("loginBySmsCode")
    @ApiOperation(value = "手机号登录")
    @LogOperation("手机号登录")
    public Result loginBySmsCode(HttpServletRequest request, @RequestBody LoginBySmsCodeDTO login) {
        //效验数据
        ValidatorUtils.validateEntity(login);
        SysUserDTO userMobile = new SysUserDTO();
        Result result = new Result<>();
        // 判断如果系统模式为op时
        if (Constant.SYSTEM_MODEL.equals(SystemModelEnum.MODEL_OP.value())) {
            Map<String, Object> codeMap = CustomLicenseManager.codeMap;
            int allUserCount = sysUserTokenService.getAllCompUserCount();
            if (allUserCount > Integer.parseInt(codeMap.get("consumerAmount").toString())) {
                return result.error(ErrorCode.LOGIN_USER_COUNT_ERROR);
            }
        }
        if (RegularUtils.isMobile(login.getMobile())) {
            //手机用户信息
            SysLogLoginEntity log = new SysLogLoginEntity();
            userMobile = sysUserService.getByMobile(login.getMobile());
            //手机用户不存在
            if (userMobile == null) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(login.getMobile());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.MOBILE_NOT_EXIST);
            }
            log.setOperation(LoginOperationEnum.LOGIN.value());
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
            log.setIp(IpUtils.getIpAddr(request));
            log.setCreateDate(new Date());
            log.setIp(IpUtils.getIpAddr(request));

            //手机动态码是否正确并且检查时效性
            SysSmsContentEntity sysSmsContentEntity = sysSmsContentService
                .getByMobile(login.getMobile());
            if (!sysSmsContentEntity.getSmsCode().equals(login.getSmscode())) {
                return result.error(ErrorCode.SMS_ERROR);
            } else if (Calendar.getInstance().getTime()
                .after(sysSmsContentEntity.getSmsExpiresAt())) {
                return result.error(ErrorCode.SMSCODE_ERROR);
            }
            //登录成功
            log.setStatus(LoginStatusEnum.SUCCESS.value());
            log.setCreator(userMobile.getId());
            log.setCreatorName(userMobile.getMobile());
            sysLogLoginService.save(log);
        } else if (RegularUtils.isEmail(login.getMobile())) {
            SysLogLoginEntity log = new SysLogLoginEntity();
            //手机用户信息
            userMobile = ConvertUtils
                .sourceToTarget(sysUserService.getEntityByEmail(login.getMobile()),
                    SysUserDTO.class);
            //手机用户不存在
            if (userMobile == null) {
                log.setStatus(LoginStatusEnum.FAIL.value());
                log.setCreatorName(login.getMobile());
                sysLogLoginService.save(log);
                return result.error(ErrorCode.EMAIL_NOT_EXIST);
            }

            log.setOperation(LoginOperationEnum.LOGIN.value());
            log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
            log.setIp(IpUtils.getIpAddr(request));
            log.setCreateDate(new Date());
            log.setIp(IpUtils.getIpAddr(request));

            //手机动态码是否正确并且检查时效性
            SysEmailContentEntity emailContent = sysEmailContentService
                .getByEmail(login.getMobile());
            if (!emailContent.getEmailCode().equals(login.getSmscode())) {
                return result.error(ErrorCode.SMS_ERROR);
            } else if (Calendar.getInstance().getTime().after(emailContent.getEmailExpiresAt())) {
                return result.error(ErrorCode.SMSCODE_ERROR);
            }
            //登录成功
            log.setStatus(LoginStatusEnum.SUCCESS.value());
            log.setCreator(userMobile.getId());
            log.setCreatorName(userMobile.getMobile());
            sysLogLoginService.save(log);
        }

        return sysUserTokenService.createToken(userMobile.getId());
    }

    @PostMapping("logout")
    @ApiOperation(value = "退出")
    @LogOperation("退出")
    public Result logout(HttpServletRequest request, @RequestBody LoginOutDTO loginOutDTO) {
        UserDetail user = SecurityUser.getUser();

        //退出
        SysUserEntity sysUserEntity = sysUserService.getByUserIdOnLoginOut(user.getId());
        sysUserEntity.setDfltCompId(loginOutDTO.getCompId());
        sysUserEntity.setUpdater(user.getId());
        sysUserEntity.setUpdateDate(new Date());
        sysUserEntity.setLanguage(loginOutDTO.getLanguage());
        sysUserEntity.setUpdateTimestamp(String.valueOf(System.currentTimeMillis()));
        sysUserService.updateUserInfo(sysUserEntity);
        sysUserTokenService.logout(user.getId());
        //用户信息
        SysLogLoginEntity log = new SysLogLoginEntity();
        log.setOperation(LoginOperationEnum.LOGOUT.value());
        log.setIp(IpUtils.getIpAddr(request));
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        log.setIp(IpUtils.getIpAddr(request));
        log.setStatus(LoginStatusEnum.SUCCESS.value());
        log.setCreator(user.getId());
        log.setCreatorName(user.getUsername());
        log.setCreateDate(new Date());
        sysLogLoginService.save(log);

        return new Result<>();
    }

    /**
     * @param @param [resetDTO]
     * @return @return com.softtown.common.utils.Result
     * @throws
     * @Title: reset
     * @Description: Saas模式下账户的忘记密码
     * @author fuming
     * @date 2019/6/3 10:13
     */
    @PostMapping("reset")
    @ApiOperation(value = "重置密码")
    @LogOperation("重置密码")
    public Result reset(@RequestBody ResetDTO resetDTO) {
        //效验数据
        ValidatorUtils.validateEntity(resetDTO, UpdateGroup.class);
        SysUserEntity sysUserEntity;
        Result result = new Result<>();
        if (RegularUtils.isEmail(resetDTO.getMobile())) {
            sysUserEntity = sysUserService.getEntityByEmail(resetDTO.getMobile());
        } else if (RegularUtils.isMobile(resetDTO.getMobile())) {
            sysUserEntity = sysUserService.getEntityByMobile(resetDTO.getMobile());
        } else {
            sysUserEntity = sysUserService.getUserByAccount(resetDTO.getMobile());
        }

        if (resetDTO.getPassword().equals(resetDTO.getNewpwd())) {
            sysUserService.updatePassword(sysUserEntity.getId(), resetDTO.getNewpwd());
        } else if (!RegularUtils.ispwd(resetDTO.getPassword()) && !RegularUtils
            .ispwd(resetDTO.getNewpwd())) {
            return result.error(ErrorCode.PWD_ERROR);
        } else {
            return result.error(ErrorCode.PASSWORD_SAME_ERROR);
        }
        return result;
    }

    @PostMapping("appealToPlatform")
    @ApiOperation(value = "向平台申诉")
    @LogOperation("向平台申诉")
    public Result appealToPlatform(@RequestBody AppealDTO appealDTO) {
        // 暂时待定
        SysFeedBackEntity sysFeedBackEntity = new SysFeedBackEntity();
        sysFeedBackEntity.setContent("平台申诉找回密码");
        sysFeedBackEntity.setTitle("找回密码");
        sysFeedBackEntity.setType(FeedBackTypeEnum.OTHER.value());
        sysFeedBackEntity.setFbHasAttDoc(FeedbackStatusEnum.OPEN.value());
        sysFeedBackEntity
            .setContent(appealDTO.getSelfMobile().concat(",").concat(appealDTO.getSelfEmail()));
        sysFeedBackEntity.setFbDate(new Date());
        return new Result<>();
    }

    @PostMapping("changeInitPwd")
    @ApiOperation(value = "修改如果是初始密码")
    @LogOperation("修改如果是初始密码")
    public Result changeInitPwd(@RequestBody LoginDTO loginDTO) {
        if (RegularUtils.isEmail(loginDTO.getUsername())) {
            SysUserEntity sysUserEntity = sysUserService.getEntityByEmail(loginDTO.getUsername());
            if (sysUserEntity != null) {
                sysUserEntity.setPassword(PasswordUtils.encode(loginDTO.getPassword()));
                sysUserEntity.setIsInitPassword(UserStatusEnum.DISABLE.value());
                sysUserEntity.setUpdateTimestamp(String.valueOf(System.currentTimeMillis()));
                sysUserEntity.setUpdateDate(new Date());
                sysUserEntity.setUpdater(sysUserEntity.getId());
                sysUserService.updateUserInfo(sysUserEntity);
            }
        } else if (RegularUtils.isMobile(loginDTO.getUsername())) {
            SysUserEntity sysUserEntity = sysUserService.getEntityByMobile(loginDTO.getUsername());
            if (sysUserEntity != null) {
                sysUserEntity.setIsInitPassword(UserStatusEnum.DISABLE.value());
                sysUserEntity.setUpdateTimestamp(String.valueOf(System.currentTimeMillis()));
                sysUserEntity.setUpdateDate(new Date());
                sysUserEntity.setPassword(PasswordUtils.encode(loginDTO.getPassword()));
                sysUserEntity.setUpdater(sysUserEntity.getId());
                sysUserService.updateUserInfo(sysUserEntity);
            }
        } else {
            SysUserEntity sysUserEntity = sysUserService.getUserByAccount(loginDTO.getUsername());
            if (sysUserEntity != null) {
                sysUserEntity.setUpdateDate(new Date());
                sysUserEntity.setPassword(PasswordUtils.encode(loginDTO.getPassword()));
                sysUserEntity.setUpdateTimestamp(String.valueOf(System.currentTimeMillis()));
                sysUserEntity.setUpdater(sysUserEntity.getId());
                sysUserEntity.setIsInitPassword(UserStatusEnum.DISABLE.value());
                sysUserService.updateUserInfo(sysUserEntity);
            }
        }
        return new Result<>();
    }

    @PostMapping("getOpenId")
    @ApiOperation(value = "获取")
    @LogOperation("获取")
    public Result<String> getOpenId(@RequestBody WxOpenIdDTO wxOpenIdDTO) {
        //获取云存储配置信息
        MiniProgramConfig config = sysParamsService
            .getValueObject(Constant.MINIPROGRAM_CONFIG_KEY, MiniProgramConfig.class);
        String openid = null;
        if (config.getType().equals(MiniService.WECHAT.getValue())) {
            //向微信后台发起请求获取openid的url
            String WX_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
            //替换appid，appsecret，和code
            String requestUrl = WX_URL.replace("APPID", config.getWxAppId()).
                replace("SECRET", config.getWxAppSercet()).replace("JSCODE", wxOpenIdDTO.getCode()).
                replace("authorization_code", "authorization_code");
            //调用get方法发起get请求，并把返回值赋值给returnvalue
            String returnValue = get(requestUrl);
            //定义一个json对象。
            JSONObject jsonObject = JSONObject.fromObject(returnValue);
            openidMap.put(jsonObject.getString("openid"), jsonObject.getString("session_key"));
            openid = jsonObject.getString("openid");
        }

        return new Result<String>().ok(openid);
    }

    /**
     * 发起get请求的方法。
     *
     * @param url
     * @return
     */
    public static String get(String url) {
        String result = "";
        BufferedReader in = null;
        InputStream is = null;
        InputStreamReader isr = null;
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.connect();
            Map<String, List<String>> map = conn.getHeaderFields();
            is = conn.getInputStream();
            isr = new InputStreamReader(is);
            in = new BufferedReader(isr);
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            // 异常记录
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (is != null) {
                    is.close();
                }
                if (isr != null) {
                    isr.close();
                }
            } catch (Exception e2) {
                // 异常记录
            }
        }
        return result;
    }


    @GetMapping(value = "getPhoneNumber")
    @ApiOperation(value = "微信授权登录")
    @LogOperation("微信授权登录")
    public Result<String> getPhoneNumber(@RequestParam("openid") String openid,
        @RequestParam("iv") String iv, @RequestParam("encryptedData") String encryptedData) {
        String token = null;
        try {
            Map<String, Object> openidMap = LoginController.openidMap;
            String sessionKey = openidMap.get(openid).toString();
            //根据id数据库数据查询
            SysUserEntity userEntity = sysUserService
                .getOne(new QueryWrapper<SysUserEntity>().lambda()
                    .eq(SysUserEntity::getWxMpOpenid, openid));

            //如果user等于null说明该用户第一次登录，数据库没有该用户信息。
            if (userEntity == null) {
                //如果没有openid，说明没有授权过
                AES aes = new AES();
                byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData),
                    Base64.decodeBase64(sessionKey),
                    Base64.decodeBase64(iv));
                if (null != resultByte && resultByte.length > 0) {
                    String userInfo = new String(resultByte, "UTF-8");
                    JSONObject fromObject = JSONObject.fromObject(userInfo);
                    SysUserEntity userEntity1 = sysUserService
                        .getOne(new QueryWrapper<SysUserEntity>().lambda()
                            .eq(SysUserEntity::getMobile,
                                fromObject.getString("phoneNumber")));
                    System.err.println(fromObject.toString());
                    if (userEntity1 != null) {
                        userEntity1.setWxMpOpenid(openid);
                        sysUserService.updateById(userEntity1);
                        token = JSONObject.fromObject(
                            sysUserTokenService.createToken(userEntity1.getId()).getData())
                            .getString("token");
                        ;
                    }
                }
            } else {
                token = JSONObject
                    .fromObject(sysUserTokenService.createToken(userEntity.getId()).getData())
                    .getString("token");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result<String>().ok(token);
    }

    @PostMapping("getTokenByOpenId")
    @ApiOperation(value = "通过openid获取token")
    @LogOperation("通过openid获取token")
    public Result<String> getTokenByOpenId(@RequestBody LoginOpenIdDTO loginOpenIdDTO) {
        String token = null;
        //根据openid数据库数据查询
        SysUserEntity userEntity = sysUserService
            .getOne(new QueryWrapper<SysUserEntity>().lambda()
                .eq(SysUserEntity::getWxMpOpenid, loginOpenIdDTO.getOpenid()));
        if (userEntity != null) {
            token = JSONObject
                .fromObject(sysUserTokenService.createToken(userEntity.getId()).getData())
                .getString("token");
        }

        return new Result<String>().ok(token);
    }
}